function isReveredTag(tag) {
    const tagList = ['a', 'div', 'img', 'button', 'input', 'p', 'span'];
    return tagList.includes(tag)
}


export function createElement(vm, tag, data = {}, ...children) { // _c('my-button')
    debugger;
    // 可能要创造组件的虚拟节点
    if (isReveredTag(tag)) {
        // 创建元素的虚拟节点
        return vnode(vm, tag, data, children, data.key, null)
    } else {
        // 创造组件的虚拟节点 ， 组件需要找到组件的模板去进行渲染
        let Ctor = vm.$options.components[tag]; // 可能是对象 也有可能是一个类
        // 稍后我们会初始化组件 需要组件的构造函数

        return createComponent(vm, tag, data, children, data.key, Ctor);
    }
}
const init = (vnode) => {
    // 组件的虚拟节点上有组件的实例
    const child = vnode.componentInstance = new vnode.componentOptions.Ctor({}); // 放插槽属性。。。
    child.$mount(); // 会做组件对应的编译  会在组件的实例上添加一个$el属性

    // vnode.componentInstance.$el => button按钮

}

function createComponent(vm, tag, data, children, key, Ctor) {
    if (typeof Ctor === 'object' && Ctor !== null) {
        const VueCtor = vm.$options._base;
        Ctor = VueCtor.extend(Ctor); // 组件内部声明的components属性也会被包装成类
    }
    data.hook = { // 稍后我们通过虚拟节点创造真实节点的时候 ，就调用这个init方法
        init
    }
    return vnode(vm, tag, data, undefined, key, undefined, { Ctor, children });
}


// 先将模板变成了ast语法树 -》 生成了render函数 -》 创造虚拟节点 （虚拟节点可能是元素、可能是组件） ， 如果是组件就创造组件的虚拟节点 （data.hook,componentOptions里面放着组件的Ctor） -》 创造真实节点 -> 组件会调用init （创造组件的实例并且挂载）


export function createTextNode(vm, text) {
    return vnode(vm, undefined, undefined, undefined, undefined, text)
}

function vnode(vm, tag, data, children, key, text, componentOptions) {
    return {
        vm,
        tag,
        data,
        children,
        key,
        text,
        componentOptions
        // ...
    }
}